package weibo;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

public class DecodeWeiboCaptcha {

	public static void cleanImage(BufferedImage cImg) {
		List<Integer> blockers = getBlockColors(cImg);
		for (int y = 0; y < cImg.getHeight(); y++) {
			for (int x = 0; x < cImg.getWidth(); x++) {
				int rgb = cImg.getRGB(x, y);
				if (blockers.contains(rgb)) {
					cImg.setRGB(x, y, Color.white.getRGB());
				}
			}
		}

		removeParticles(cImg);
		blackToColor(cImg, Color.red);
		removeblack(cImg);
		bringBackBlack(cImg);
		removeParticles(cImg);
		removeBar(cImg);
		remove3Bar(cImg);
	}
	
	public static List<BufferedImage> getListSub(BufferedImage img){
		int start = 0;
		List<BufferedImage> list = new ArrayList<BufferedImage>();
		for(int y=1;y<6;y++){
			Rectangle rectangle = findLetterRectangle(img,start);
			start = rectangle.x+rectangle.width+1;
			if(rectangle.height ==0 || rectangle.width == 0){
				continue;
			}
			BufferedImage subCode = img.getSubimage(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
			list.add(subCode);
		}
		return list;
	}
	
	public static Rectangle findLetterRectangle(BufferedImage img, int startX){
	    Rectangle rectangle= new Rectangle();
	    boolean findX = false; 
	    int collatural = 0; 
	    OUTSIDE: for (int x = startX; x < img.getWidth(); x++) {
	        for (int y = 0; y < img.getHeight(); y++) {
	            // find x
	            if (!findX && !WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils.getColorByXY(img, x, y))) { 
	                rectangle.x = x;
	                findX = true;
	            }
	            // find width
	            if(findX){
	                if(WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils.getColorByXY(img, x, y))){
	                    if(y >= img.getHeight() - 1){
	                        rectangle.width = x - rectangle.x;
	                        collatural = x;
	                        break OUTSIDE;
	                    }
	                }else {
	                    break;
	                }
	            }
	        }
	    }
	    
	    // find y&height
	    boolean findY = false; 
	    OUTSIDE: for (int y = 0; y < img.getHeight(); y++) {
	        for (int x = startX; x < collatural+1; x++) {
	            // find y
	            if (!findY && !WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils.getColorByXY(img, x, y))) { 
	                rectangle.y = y;
	                findY = true;
	            }
	            // find height
	            if(findY){
	                if(WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils.getColorByXY(img, x, y))){
	                    if(x >= collatural){
	                        rectangle.height = y - rectangle.y;
	                        break OUTSIDE;
	                    }
	                }else {
	                    break;
	                }
	            }
	        }
	    }
	    if(rectangle.height == 0){
	    	rectangle.height = img.getHeight() - rectangle.y;
	    }
		return rectangle;
	}

	public static void removeBar(BufferedImage img) {
		for (int y = 1; y < img.getHeight() - 1; y++) {
			for (int x = 2; x < img.getWidth() - 2; x++) {
				if ((img.getRGB(x, y) == img.getRGB(x + 1, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x - 1, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 2, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x, y + 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x, y - 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 1, y + 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 1, y - 1))) {
					img.setRGB(x, y, Color.white.getRGB());
					img.setRGB(x + 1, y, Color.white.getRGB());
				}
			}
		}
	}

	public static void remove3Bar(BufferedImage img) {
		for (int y = 1; y < img.getHeight() - 1; y++) {
			for (int x = 3; x < img.getWidth() - 3; x++) {
				if ((img.getRGB(x, y) == img.getRGB(x + 1, y))
						&& (img.getRGB(x, y) == img.getRGB(x + 2, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x - 1, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 3, y))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x, y + 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x, y - 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 1, y + 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 1, y - 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 2, y - 1))
						&& WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
								.getColorByXY(img, x + 2, y - 1))) {
					img.setRGB(x, y, Color.white.getRGB());
					img.setRGB(x + 1, y, Color.white.getRGB());
					img.setRGB(x + 2, y, Color.white.getRGB());
				}
			}
		}
	}

	public static void removeblack(BufferedImage cImg) {
		for (int y = 0; y < cImg.getHeight(); y++) {
			for (int x = 0; x < cImg.getWidth(); x++) {
				Color black = new Color(4, 2, 4);
				if (cImg.getRGB(x, y) == black.getRGB()) {
					cImg.setRGB(x, y, Color.white.getRGB());
				}
			}
		}

	}

	public static void bringBackBlack(BufferedImage cImg) {
		for (int y = 0; y < cImg.getHeight() - 1; y++) {
			for (int x = 0; x < cImg.getWidth() - 1; x++) {
				Color red = new Color(108, 78, 100);
				if (cImg.getRGB(x, y) == red.getRGB()) {
					cImg.setRGB(x, y, Color.BLACK.getRGB());
				}
			}
		}

	}

	public static void blackToColor(BufferedImage cImg, Color color) {
		for (int y = 1; y < cImg.getHeight() - 1; y++) {
			for (int x = 1; x < cImg.getWidth() - 1; x++) {
				Color black = new Color(4, 2, 4);
				if (cImg.getRGB(x, y) != black.getRGB()) {
					continue;
				}
				if ((!WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
						.getColorByXY(cImg, x - 1, y)))
						&& (!WeiboCrackerUtils
								.isWhiteLikeColor(WeiboCrackerUtils
										.getColorByXY(cImg, x + 1, y)))
						&& (!WeiboCrackerUtils
								.isWhiteLikeColor(WeiboCrackerUtils
										.getColorByXY(cImg, x, y + 1)))
						&& (!WeiboCrackerUtils
								.isWhiteLikeColor(WeiboCrackerUtils
										.getColorByXY(cImg, x, y - 1)))) {
					cImg.setRGB(x, y, color.getRGB());
				}
			}
		}

	}

	// stripe off the noise dots
	public static void removeParticles(BufferedImage cImg) {
		for (int y = 0; y < cImg.getHeight(); y++) {
			for (int x = 0; x < cImg.getWidth(); x++) {
				if (WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
						.getColorByXY(cImg, x, y))) {
					continue;
				}
				if (x == 0 && y == 0 || x == 0 && y == cImg.getHeight() - 1
						|| x == cImg.getWidth() - 1 && y == 0
						|| x == cImg.getWidth() - 1
						&& y == cImg.getHeight() - 1) {
					cImg.setRGB(x, y, Color.WHITE.getRGB());
				} else if (x == 0) {
					if (WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
							.getColorByXY(cImg, x, y + 1))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x, y - 1))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x + 1, y))) {
						cImg.setRGB(x, y, Color.WHITE.getRGB());
					}
				} else if (x == cImg.getWidth() - 1) {
					if (WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
							.getColorByXY(cImg, x, y + 1))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x, y - 1))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x - 1, y))) {
						cImg.setRGB(x, y, Color.WHITE.getRGB());
					}
				} else if (y == 0) {
					if (WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
							.getColorByXY(cImg, x - 1, y))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x + 1, y))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x, y + 1))) {
						cImg.setRGB(x, y, Color.WHITE.getRGB());
					}
				} else if (y == cImg.getHeight() - 1) {
					if (WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
							.getColorByXY(cImg, x - 1, y))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x + 1, y))
							&& WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x, y - 1))) {
						cImg.setRGB(x, y, Color.WHITE.getRGB());
					}
				} else {
					if ((WeiboCrackerUtils.isWhiteLikeColor(WeiboCrackerUtils
							.getColorByXY(cImg, x, y + 1)))
							&& (WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x - 1, y)))
							&& (WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x + 1, y)))
							&& (WeiboCrackerUtils
									.isWhiteLikeColor(WeiboCrackerUtils
											.getColorByXY(cImg, x, y - 1)))) {
						cImg.setRGB(x, y, Color.WHITE.getRGB());
					}
				}
			}
		}
	}

	// return off the block colors
	public static List<Integer> getBlockColors(BufferedImage cImg){

		List<Integer> blockColors = new ArrayList<Integer>();

		for (int y = 1; y < cImg.getHeight() - 1; y++) {
			for (int x = 1; x < cImg.getWidth() - 1; x++) {
				int rgb = cImg.getRGB(x, y);
				if (rgb != Color.WHITE.getRGB()
						&& rgb != Color.BLACK.getRGB()
						&& WeiboCrackerUtils.isLightColor(rgb)
						&& WeiboCrackerUtils
								.isLightColor(cImg.getRGB(x - 1, y))
						&& WeiboCrackerUtils
								.isLightColor(cImg.getRGB(x + 1, y))
						&& WeiboCrackerUtils
								.isLightColor(cImg.getRGB(x, y - 1))
						&& WeiboCrackerUtils
								.isLightColor(cImg.getRGB(x, y + 1))) {
					blockColors.add(rgb);
				}

			}
		}

		return blockColors;

	}
}
